#pragma once

#include <iostream>
#include <string>
#include <cstdio>
#include <cstring>
#include <time.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#define SIZE 1024

#define Info    0
#define Debug   1
#define Warning 2
#define Error   3
#define Fatal   4

#define Screen    0
#define Onefile   1
#define Classfile 2

#define LogFile "log.txt"

class Log
{
public:
    Log()
    {
        printMethod = 0;   // 默认向显示器打印
        path = "./log/";
    }

    void Enable(int method)
    {
        printMethod = method;
    }

    std::string levelToString(int level)
    {
        switch(level)
        {
            case Info: 
                return "Info";
            case Debug: 
                return "Debug";
            case Warning: 
                return "Warning";
            case Error: 
                return "Error";
            case Fatal: 
                return "Fatal";
            default: 
                return "None";
        }
    }

    // void logmessage(int level, const char* format, ...)
    // {
    //     time_t t = time(nullptr); 
    //     struct tm* ctime = localtime(&t);
    //     char leftbuffer[SIZE];
    //     snprintf(leftbuffer, sizeof(leftbuffer), "[%s][%d-%02d-%02d %02d:%02d:%02d]",
    //     levelToString(level).c_str(), ctime->tm_year + 1900, ctime->tm_mon + 1, ctime->tm_mday,
    //     ctime->tm_hour, ctime->tm_min, ctime->tm_sec);

    //     va_list s;
    //     va_start(s, format);
    //     char rightbuffer[SIZE];
    //     vsnprintf(rightbuffer, sizeof(rightbuffer), format, s);
    //     va_end(s);
    
    //     char logtxt[SIZE*2];
    //     snprintf(logtxt, sizeof(logtxt), "%s %s\n", leftbuffer, rightbuffer);
    //     // std::cout << logtxt;
    //     printLog(level, logtxt);
    // }

    void operator()(int level, const char* format, ...)
    {
        time_t t = time(nullptr); 
        struct tm* ctime = localtime(&t);
        char leftbuffer[SIZE];
        snprintf(leftbuffer, sizeof(leftbuffer), "[%s][%d-%02d-%02d %02d:%02d:%02d]",
        levelToString(level).c_str(), ctime->tm_year + 1900, ctime->tm_mon + 1, ctime->tm_mday,
        ctime->tm_hour, ctime->tm_min, ctime->tm_sec);

        va_list s;
        va_start(s, format);
        char rightbuffer[SIZE];
        vsnprintf(rightbuffer, sizeof(rightbuffer), format, s);
        va_end(s);
    
        char logtxt[SIZE*2];
        snprintf(logtxt, sizeof(logtxt), "%s %s\n", leftbuffer, rightbuffer);
        // std::cout << logtxt;
        printLog(level, logtxt);
    }

    void printLog(int level, const std::string& logtxt)
    {
        switch(printMethod)
        {
            case Screen:
                std::cout << logtxt;
                break;
            case Onefile:
                printOneFile(LogFile, logtxt);
                break;
            case Classfile:
                printClassFile(level, logtxt);
                break;
        }
    }


    void printOneFile(const std::string& logname, const std::string& logtxt)
    {
        std::string _logname = path + logname;
        int fd = open(_logname.c_str(), O_CREAT|O_WRONLY|O_APPEND, 0666);
        if (fd < 0) return;
        write(fd, logtxt.c_str(), logtxt.size());
        close(fd);
    }

    void printClassFile(int level, const std::string& logtxt)
    {
        std::string logname = LogFile;
        logname += ".";
        logname += levelToString(level);
        printOneFile(logname, logtxt);
    }

    private:
    int printMethod;
    std::string path;
};



// int sum(int n, ...)
// {
//     va_list s;       // 定义一个char*指针
//     va_start(s, n);  // 让s指向第一个可变参数
//     int num = 0;
//     while (n--)
//     {
//         num += va_arg(s, int); // 获取s指向的数据
//     }
//     va_end(s);   // 将s置空
//     return num;
// }